string
number
boolean
null
undefined
symbol
bigint
object
array
function
const
for all of your references;
avoid using var. eslint: [prefer- const](https:
//eslint.org/docs/rules/prefer-
const.html), [no- const-assign](https:
//eslint.org/docs/rules/no-
const-assign.html)
Why? This ensures that you can't reassign your references, which can lead to bugs and difficult to comprehend code.
let
instead of var. eslint: [no-var](https:
let
and `
are block-scoped, whereasvar` is function-scoped.
no-new-object](https:
//eslint.org/docs/rules/no-new-object.html)
object-shorthand](https:
object-shorthand](https:
quote-props](https:
Object.prototype
methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf. eslint: [no-prototype-builtins](https:
Object.assign](https:
prefer-object-spread](https:
//eslint.org/docs/rules/prefer-object-spread)
no-array- constructor](https:
//eslint.org/docs/rules/no-array-
constructor.html)
...
to copy arrays.
...
instead of [Array.from](https:
Array.from](https:
Array.from](https:
...
for mapping over iterables, because it
avoids creating an intermediate
array.
array-callback-return](https:
prefer-destructuring](https:
//eslint.org/docs/rules/prefer-destructuring)
Why? Destructuring saves you from creating temporary references for those properties, and from repetitive access of the object. Repeating object access creates more repetitive code, requires more reading, and creates more opportunities for mistakes. Destructuring objects also provides a single site of definition of the object structure that is used in the block, rather than requiring reading the entire block to determine what is used.
prefer-destructuring](https:
''
for strings. eslint: [quotes](https:
//eslint.org/docs/rules/quotes.html)
prefer-template](https:
template-curly-spacing](https:
//eslint.org/docs/rules/template-curly-spacing)
eval()
on a string, it opens too many
vulnerabilities. eslint: [no-eval](https:
no-useless-escape](https:
//eslint.org/docs/rules/no-useless-escape)
Why? Backslashes harm readability, thus they should only be present when necessary.
func-style](https:
//eslint.org/docs/rules/func-style)
Why? Function declarations are hoisted, which means that it's easy - too easy - to reference the function before it is defined in the file. This harms readability and maintainability. If you find that a function's definition is large or complex enough that it is interfering with understanding the rest of the file, then perhaps it's time to extract it to its own module! Don't forget to explicitly name the expression, regardless of whether or not the name is inferred from the containing variable (which is often the case in modern browsers or when using compilers such as Babel). This eliminates any assumptions made about the Error's call stack. ([Discussion](https: //github.com/airbnb/javascript/issues/794))
wrap-iife](https:
if, while, etc). Assign the function to a
variable instead. Browsers will
allow you to do it, but they all
interpret it differently, which is
bad news bears. eslint: [no-loop-func](https:
block
as a list of statements. A
function declaration is not a
statement.
arguments. This will take precedence over
the arguments
object that is given to every
function scope.
arguments, opt to use rest syntax ...
instead. eslint: [prefer-rest-params](https:
default-param-last](https:
no-new-func](https:
//eslint.org/docs/rules/no-new-func)
space-before-function-paren](https:
space-before-blocks](https:
//eslint.org/docs/rules/space-before-blocks)
no-param-reassign](https:
no-param-reassign](https:
...
to call variadic functions. eslint:
[prefer-spread](https:
function-paren-newline](https:
prefer-arrow-callback](https:
//eslint.org/docs/rules/prefer-arrow-callback.html),
[arrow-spacing](https:
//eslint.org/docs/rules/arrow-spacing.html)
Why? It creates a version of the function that executes in the context ofthis, which is usually what you want, and is a more concise syntax.
Why not? If you have a fairly complicated function, you might move that logic out into its own named function expression.
return
statement. eslint: [arrow-parens](https:
//eslint.org/docs/rules/arrow-parens.html),
[arrow-body-style](https:
//eslint.org/docs/rules/arrow-body-style.html)
arrow-parens](https:
=>) with comparison operators (<=, >=). eslint: [no-confusing-arrow](https:
implicit-arrow-linebreak](https:
class. Avoid manipulating prototype
directly.
Why?classsyntax is more concise and easier to reason about.
extends
for inheritance.
this
to help with method chaining.
toString()
method, just make sure it works
successfully and causes no side
effects.
no-useless- constructor](https:
//eslint.org/docs/rules/no-useless-
constructor)
no-dupe-class-members](https:
this
or be made into a static method
unless an external library or
framework requires using specific
non-static methods. Being an
instance method should indicate that
it behaves differently based on
properties of the receiver. eslint:
[class-methods-use-this](https:
import/export) over a non-standard module
system. You can always transpile
to your preferred module
system.
Why? Modules are the future, let's start using the future now.
no-duplicate-imports](https:
import/no-mutable-exports](https:
import/prefer-default-export](https:
imports above non-import statements.
eslint: [import/first](https:
object-curly-newline](https:
import/no-webpack-loader-syntax](https:
import/extensions](https:
for-in
or for-of. eslint: [no-iterator](https:
//eslint.org/docs/rules/no-iterator.html)
[no-restricted-syntax](https:
//eslint.org/docs/rules/no-restricted-syntax)
Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.
Usemap()/every()/filter()/find()/findIndex()/reduce()/some()/ ... to iterate over arrays, andObject.keys()/Object.values()/Object.entries()to produce arrays so you can iterate over objects.
generator-star-spacing](https:
//eslint.org/docs/rules/generator-star-spacing)
Why?functionand*are part of the same conceptual keyword -*is not a modifier forfunction,function*is a unique construct, different fromfunction.
dot-notation](https:
//eslint.org/docs/rules/dot-notation.html)
[]
when accessing properties with a
variable.
**
when calculating exponentiations.
eslint: [no-restricted-properties](https:
const
or let
to declare variables. Not doing
so will result in global
variables. We want to avoid
polluting the global namespace.
Captain Planet warned us of
that. eslint: [no-undef](https:
//eslint.org/docs/rules/no-undef)
[prefer- const](https:
//eslint.org/docs/rules/prefer-
const)
orlet
declaration per variable or
assignment. eslint: [one-var`](https:
//eslint.org/docs/rules/one-var.html)
s and then group all your let`s.
no-multi-assign](https:
++, --). eslint [no-plusplus](https:
=
in an assignment. If your assignment
violates [max-len](https:
operator-linebreak](https:
//eslint.org/docs/rules/operator-linebreak.html).
no-unused-vars](https:
var
declarations get hoisted to the
top of their closest enclosing
function scope, their assignment
does not. const
and let
declarations are blessed with a
new concept called [Temporal
Dead Zones (TDZ)](https:
//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz).
It's important to know why
[typeof is no longer
safe](https:
//web.archive.org/web/20200121061528/http:
//es-discourse.com/t/why-typeof-is-no-longer-safe/15).
===
and !==
over ==
and !=. eslint: [eqeqeq](https:
//eslint.org/docs/rules/eqeqeq.html)
if
statement evaluate their
expression using coercion with
the ToBoolean
abstract method and always
follow these simple rules:
'', otherwise true
case
and default
clauses that contain lexical
declarations (e.g. let, const, function, and class). eslint: [no-case-declarations](https:
//eslint.org/docs/rules/no-case-declarations.html)
Why? Lexical declarations are visible in the entireswitchblock but only get initialized when assigned, which only happens when itscaseis reached. This causes problems when multiplecaseclauses attempt to define the same thing.
no-nested-ternary](https:
no-unneeded-ternary](https:
+, -, and **
since their precedence is broadly
understood. We recommend enclosing /
and *
in parentheses because their
precedence can be ambiguous when
they are mixed. eslint: [no-mixed-operators](https:
nonblock-statement-body-position](https:
//eslint.org/docs/rules/nonblock-statement-body-position)
if
and else, put else
on the same line as your if
block's closing brace. eslint:
[brace-style](https:
if
block always executes a return
statement, the subsequent else
block is unnecessary. A return
in an else if
block following an if
block that contains a return
can be separated into multiple if
blocks. eslint: [no-else-return](https:
if, while
etc.) gets too long or exceeds
the maximum line length, each
(grouped) condition could be put
into a new line. The logical
operator should begin the
line.
Why? Requiring operators at the beginning of the line keeps the operators aligned and follows a pattern similar to method chaining. This also improves readability by making it easier to visually follow complex logic.
/** ... */
for multiline comments.
spaced-comment](https:
FIXME
or TODO
helps other developers quickly
understand if you're pointing
out a problem that needs to be
revisited, or if you're
suggesting a solution to the problem
that needs to be implemented. These
are different than regular comments
because they are actionable. The
actions are FIXME: -- need to figure this
out
or TODO: -- need to implement.
// FIXME:
to annotate problems.
indent](https:
//eslint.org/docs/rules/indent.html)
space-before-blocks](https:
if, while
etc.). Place no space between the
argument list and the function name
in function calls and declarations.
eslint: [keyword-spacing](https:
space-infix-ops](https:
eol-last](https:
newline-per-chained-call](https:
no-whitespace-before-property](https:
//eslint.org/docs/rules/no-whitespace-before-property)
padded-blocks](https:
no-multiple-empty-lines](https:
space-in-parens](https:
array-bracket-spacing](https:
object-curly-spacing](https:
max-len](https:
block-spacing](https:
comma-spacing](https:
computed-property-spacing](https:
func-call-spacing](https:
key-spacing](https:
no-trailing-spaces](https:
no-multiple-empty-lines](https:
//eslint.org/docs/rules/no-multiple-empty-lines)
comma-style](https:
//eslint.org/docs/rules/comma-style.html)
comma-dangle](https:
semi](https:
//eslint.org/docs/rules/semi.html)
Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called [Automatic Semicolon Insertion](https: //tc39.github.io/ecma262/#sec-automatic-semicolon-insertion) to determine whether it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues.
no-new-wrappers](https:
//eslint.org/docs/rules/no-new-wrappers)
Number
for type casting and parseInt
always with a radix for parsing
strings. eslint: [radix](https:
no-new-wrappers](https:
//eslint.org/docs/rules/no-new-wrappers)
parseInt
is your bottleneck and need to use
Bitshift for [performance
reasons](https:
no-new-wrappers](https:
id-length](https:
//eslint.org/docs/rules/id-length)
camelcase](https:
new-cap](https:
//eslint.org/docs/rules/new-cap.html)
no-underscore-dangle](https:
this. Use arrow functions or
[Function#bind](https:
const
(it can not be reassigned), and (3)
the programmer can trust it (and its
nested properties) to never
change.
getVal()
and setVal('hello').
boolean, use isVal()
or hasVal().
get()
and set()
functions, but be consistent.
$.
$('.sidebar ul')
or parent > child $('.sidebar >
ul'). [jsPerf](https:
find
with scoped jQuery object
queries.
Why? [They are not finalized](https: //tc39.github.io/process-document/), and they are subject to change or to be withdrawn entirely. We want to use JavaScript, and proposals are not JavaScript yet.
Number.isNaN
instead of global isNaN. eslint: [no-restricted-globals](https:
//eslint.org/docs/rules/no-restricted-globals)
Why? The globalisNaNcoerces non-numbers to numbers, returning true for anything that coerces to NaN. If this behavior is desired, make it explicit.
Number.isFinite
instead of global isFinite. eslint: [no-restricted-globals](https:
mocha](https:
//www.npmjs.com/package/mocha)
and [jest](https:
//www.npmjs.com/package/jest) at
Airbnb. [tape](https:
//www.npmjs.com/package/tape) is
also used occasionally for
small, separate modules.
map(), reduce(), and filter()
optimized for traversing
arrays?](https:
//www.quora.com/JavaScript-programming-language-Are-Javascript-functions-like-map-reduce-and-filter-already-optimized-for-traversing-array/answer/Quildreen-Motta)